///****************************************
// * Copyright (c) 2015 NiuWa.
// * All rights reserved.
// * Created on 2015年4月15日
// * 
// * Contributors:
// * 	   Percy.Lo - initial implementation
// ****************************************/
//package com.niuwa.p2p.service.impl.exchange;
//
//import java.math.BigDecimal;
//import java.math.RoundingMode;
//import java.util.ArrayList;
//import java.util.LinkedList;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.TimeUnit;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//
//import com.mongodb.BasicDBObject;
//import com.mongodb.DBObject;
//import com.niuwa.p2p.core.enums.GatheringFoundType;
//import com.niuwa.p2p.core.enums.MongoQueueEnum;
//import com.niuwa.p2p.core.enums.QueueScanType;
//import com.niuwa.p2p.core.utils.DictConstant.ReleaseStatus;
//import com.niuwa.p2p.core.utils.DictConstant.TranferStatus;
//import com.niuwa.p2p.dao.business.CustClaimDao;
//import com.niuwa.p2p.dao.business.InvestProdRecordDao;
//import com.niuwa.p2p.dao.business.LoanClaimDao;
//import com.niuwa.p2p.dao.claimtransfer.TransferApplyDao;
//import com.niuwa.p2p.entity.business.CustClaim;
//import com.niuwa.p2p.entity.business.InvestProdRecord;
//import com.niuwa.p2p.entity.business.LoanClaim;
//import com.niuwa.p2p.entity.claimtransfer.TransferApply;
//import com.niuwa.p2p.server.manggoDB.exchange.ExchangeMongoDBHelper;
//import com.niuwa.p2p.server.manggoDB.exchange.FundResult;
//import com.niuwa.p2p.server.manggoDB.exchange.LoanResult;
//import com.niuwa.p2p.service.exchange.IMatchInnerService;
//import com.niuwa.p2p.service.exchange.IMatchService;
//import com.niuwa.p2p.utils.ExceptionUtils;
//
//import static com.niuwa.p2p.core.constant.Constants.*;
//import static com.niuwa.p2p.server.manggoDB.exchange.ExchangeMongoDBHelper.*;
//
///**
// * @title 借款债权项目和资金匹配服务
// *
// * @author Percy.Lo
// * @version 1.0
// * @created 2015年4月15日
// */
//@Service
//public class MatchServiceImpl implements IMatchService {
//
//	final Logger logger = LoggerFactory.getLogger(this.getClass());
//
//	@Autowired
//	private IMatchInnerService matchInnerService;
//
//	@Autowired
//	private InvestProdRecordDao investProdRecordDao;
//	
//	@Autowired
//	private LoanClaimDao loanClaimDao;
//	
//	@Autowired
//	private CustClaimDao custClaimDao;
//	
//	@Autowired
//	private TransferApplyDao transferApplyDao;
//	
//	private volatile boolean asynRuning = false;//异步允许标志
//	private volatile MongoQueueEnum asynTargetQueue = null;//异步执行的目标队列
//	
//	public MatchServiceImpl() {
//		Thread asyneExecutor = new Thread(new Runnable() {//service由spring托管，单例，所以一个环境会启动一个异步执行线程，1秒扫描一次由请求触发的task。
//			@Override
//			public void run() {
//				while(true){
//					try {
//						if(asynRuning){
//							logger.info("manual-event-fundMatch starting……！ queue:"+asynTargetQueue);
//							allQueueMatch(asynTargetQueue);
//							logger.info("manual-event-fundMatch complete.");
//						} 
//					} catch (Exception e) {
//						logger.error("asyneExecutor执行业务逻辑异常！",e);
//					}finally{
//						if(asynRuning)
//							stopExecutor();
//					}
//					try {
//						TimeUnit.SECONDS.sleep(1);
//					} catch (InterruptedException e) {
//						logger.error("asyneExecutor sleep出现异常！",e);
//					}
//				}
//			}
//		});
//		asyneExecutor.start();
//		
//		//由quartz完成
////		Thread job = new Thread(new Runnable() {//service由spring托管，单例，所以一个环境会启动一个异步执行线程，5分钟扫描一次由请求触发的task。
////			@Override
////			public void run() {
////				while(true){
////					try {
////						logger.info("match job starting……！");
////						allQueueMatch(null);
////						logger.info("match job complete.");
////						TimeUnit.MINUTES.sleep(5);
////					} catch (Exception e) {
////						logger.error("job执行业务逻辑异常！",e);
////					}
////				}
////			}
////		});
////		job.start();
//	}
//	
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#allQueueMatch(com.niuwa.p2p.core.enums.MongoQueueEnum)
//	 */
//	@Override
//	public void allQueueMatch(MongoQueueEnum targetQueue) throws Exception {
//		//执行扫描
//		Long currentBatchId=System.currentTimeMillis();
//		LoanResult loanResult = null;
//		while ((loanResult = findLoan(targetQueue, currentBatchId)) != null) {
//			MongoQueueEnum loanQueue = loanResult.getQueue();
//			DBObject loanOrClaim = loanResult.getLoan();
//			logger.info("  -->扫描到一个项目或债权： "+loanResult);
//			boolean hasFund=match(loanQueue, loanOrClaim, loanQueue == MongoQueueEnum.queueLoanApp ? QueueScanType.CBA : QueueScanType.ABC, null)[1];
//			if(!hasFund){//如果没有资金了就结束当前批次的扫描
//				break;
//			}
//		}
//	}
//
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#gatheringFoundForDirect(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
//	 */
//	@Override
//	public boolean gatheringFoundForDirect(String loanUserId, String loanId, String amount, String productVersion, String productCode,
//			String surplusAmount,String projectAmount,String investorCount){
//		DBObject loanOrClaim = new BasicDBObject(ID, loanId);// 借款项目Id
//		loanOrClaim.put(USER_ID, loanUserId);//借款人Id
//		loanOrClaim.put(lOAN_AMOUNT, amount);//调取资金的额度
//		loanOrClaim.put(VERSION, productVersion);//产品版本号
//		loanOrClaim.put("_productCode", productCode);//产品代码
//		loanOrClaim.put("_surplusAmount", surplusAmount);// 剩余可投金额
//		loanOrClaim.put("_projectAmount", projectAmount);// 该笔借款额度或渠道存量债权余额
//		loanOrClaim.put("_investorCount", investorCount);//投资人数
//		logger.info("  -->直投产品-调取资金： "+loanOrClaim);
//		return match(null, loanOrClaim, QueueScanType.ABC, GatheringFoundType.DIRECT)[0];
//	}
//	
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#gatheringFoundForTransfer(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
//	 */
//	@Override
//	public boolean gatheringFoundForTransfer(String loanUserId, String loanId, String amount, String productVersion, 
//			String productCode,String surplusAmount,String projectAmount,String investorCount, String srcCreditNo, String price, 
//			String serialNo, String recordNo, String creditVersion){
//		
//		DBObject loanOrClaim = new BasicDBObject(ID, loanId);// 借款项目Id
//		loanOrClaim.put(USER_ID, loanUserId);//出让人Id
//		loanOrClaim.put(lOAN_AMOUNT, amount);//调取资金的额度
//		loanOrClaim.put(VERSION, productVersion);//产品版本号
//		loanOrClaim.put("_productCode", productCode);//产品代码
//		loanOrClaim.put("_surplusAmount", surplusAmount);// 剩余可投金额
//		loanOrClaim.put("_projectAmount", projectAmount);// 自转产品的的债权金额
//		loanOrClaim.put("_investorCount", investorCount);//投资人数
//		loanOrClaim.put("_srcCreditNo", srcCreditNo);////出让人债权编号（自转债权调取资金才有该参数）
//		loanOrClaim.put("_price", price);//转让债权价格
//		loanOrClaim.put("_serialNo", serialNo);//债权转让申请编号
//		loanOrClaim.put("_recordNo", recordNo);//债权转让者的投资记录id
//		loanOrClaim.put("_creditVersion", creditVersion);//转让债权的版本号
//		
//		//计算转让比率（转让债权金额比上转让价格）
//		BigDecimal ratio=new BigDecimal(projectAmount).divide(new BigDecimal(price),CURRENCY_CALCULATE_SCALE,RoundingMode.DOWN);
//		//计算调取资金对应的价格
//		BigDecimal bgAmount=new BigDecimal(amount);
//		BigDecimal bgSurplusAmount=new BigDecimal(surplusAmount);
//		if(bgAmount.compareTo(bgSurplusAmount)>0){//调取资金大于可投金额
//			logger.warn("  -->自转债权-调取资金失败：调取资金大于可投金额，loanOrClaim: "+loanOrClaim);
//			return false;
//		}
//		BigDecimal actualAmount=new BigDecimal(amount).divide(ratio).setScale(CURRENCY_DB_SCALE,RoundingMode.DOWN);
//		loanOrClaim.put("_actualAmount", actualAmount.toPlainString());////调取资金对应的价格（自转债权调取资金才有该参数）
//		loanOrClaim.put("_ratio", ratio.toPlainString());//转让比率（转让债权金额比上转让价格）
//		
//		logger.info("  -->自转债权-调取资金： "+loanOrClaim);
//		return match(null, loanOrClaim, QueueScanType.ABC, GatheringFoundType.TRANSFER)[0];
//	}
//	
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#doAddLoanApp(java.util.Map)
//	 */
//	@Override
//	public boolean doAddLoanApp(Map<String, String> map){
//		try {
//			doAddProject(MongoQueueEnum.queueLoanApp, map);
//			startExecutor(MongoQueueEnum.queueLoanApp);
//			return true;
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return false;
//	}
//
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#doAddLoanTransfer(java.util.Map)
//	 */
//	@Override
//	public boolean doAddLoanTransfer(Map<String, String> map){
//		try {
//			doAddProject(MongoQueueEnum.queueLoanTransfer, map);
//			startExecutor(MongoQueueEnum.queueLoanTransfer);
//			return true;
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return false;
//	}
//
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#doAddLoan(java.util.List)
//	 */
//	@Override
//	public boolean doAddLoan(List<Map<String, String>> list){
//		try {
//			List<DBObject> newList = new ArrayList<DBObject>(list.size());
//			for (Map<String, String> map : list) {
//				if (map.get(ID) == null || map.get(lOAN_AMOUNT) == null || map.get(VERSION) == null) {
//					throw new Exception("addLoan参数丢失！");
//				}
//				BigDecimal amout=new BigDecimal(map.get(lOAN_AMOUNT));
//				if (amout.compareTo(BigDecimal.ZERO)<=0) {
//					logger.error("addLoan无效参数--> [loan_amount="+amout.toPlainString()+"]");
//					continue;
//				}
//				newList.add(new BasicDBObject(map));
//			}
//			ExchangeMongoDBHelper mongo = getInstance();
//			mongo.add(MongoQueueEnum.queueLoanChannel, newList);
//			startExecutor(MongoQueueEnum.queueLoanChannel);
//			return true;
//		} catch (Exception e) {
//			logger.error("添加借款到队列失败：->" + list, e);
//		}
//		return false;
//	}
//	
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#doAddFund(java.util.Map)
//	 */
//	@Override
//	public  boolean doAddFund(Map<String, String> map){
//		try {
//			if(checkAndLimitFund(map)){//检查参数、最低投资额度、设置单笔投资上限金额
//				ExchangeMongoDBHelper mongo = getInstance();
//				mongo.add(MongoQueueEnum.queueFundA, new BasicDBObject(map));// 进入新资金队列
//				return true;
//			}
//		} catch (Exception e) {
//			logger.error("添加资金到队列失败：-> [doAddFund], " + map, e);
//		}
//		return false;
//	}
//	
//	
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#doAddFundByRepayment(java.util.Map)
//	 */
//	@Override
//	public  boolean doAddFundByRepayment(Map<String, String> map){
//		String pecordNo=map.get(ID);
//		try {
//			//移除资金队列中老数据
//			ExchangeMongoDBHelper mongo = getInstance();
//			mongo.deleteById(MongoQueueEnum.queueFundA, pecordNo, true);
//			mongo.deleteById(MongoQueueEnum.queueFundB, pecordNo, true);
//			mongo.deleteById(MongoQueueEnum.queueFundC, pecordNo, true);
//			//重新添加到资金队列
//			if(checkAndLimitFund(map)){//检查参数、最低投资额度、设置单笔投资上限金额
//				// 进入老资金队列
//				BigDecimal investSurplusAmount = new BigDecimal(map.get(INVEST_SURPLUS_AMOUNT));// 剩余投资金额
//				if (investSurplusAmount.compareTo(BigDecimal.valueOf(400L)) > 0) {
//					mongo.add(MongoQueueEnum.queueFundB, new BasicDBObject(map));// 大于400的剩余投资金额
//				} else {
//					mongo.add(MongoQueueEnum.queueFundC, new BasicDBObject(map));// 大于等于10的剩余投资金额
//				}
//				return true;
//			}
//		} catch (Exception e) {
//			logger.error("添加资金到队列失败：-> [doAddFundByRepayment], " + map, e);
//		}
//		return false;
//	}
//	
//	
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#doAddFundByBidFailure(java.util.Map)
//	 */
//	@Override
//	public  boolean doAddFundByBidFailure(Map<String, String> map){
//		String pecordNo=map.get(ID);
//		try {
//			//移除资金队列中老数据
//			ExchangeMongoDBHelper mongo = getInstance();
//			mongo.deleteById(MongoQueueEnum.queueFundA, pecordNo, true);
//			mongo.deleteById(MongoQueueEnum.queueFundB, pecordNo, true);
//			mongo.deleteById(MongoQueueEnum.queueFundC, pecordNo, true);
//			//重新添加到资金队列
//			if(checkAndLimitFund(map)){//检查参数、最低投资额度、设置单笔投资上限金额
//				mongo.add(MongoQueueEnum.queueFundA, new BasicDBObject(map));// 进入新资金队列
//				return true;
//			}
//		} catch (Exception e) {
//			logger.error("添加资金到队列失败：-> [doAddFundByBidFailure], " + map, e);
//		}
//		return false;
//	}
//
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#doLockFund()
//	 */
//	@Override
//	public boolean doLockFund(String pecordNo) {
//		ExchangeMongoDBHelper mongo = getInstance();
//		mongo.deleteById(MongoQueueEnum.queueFundA, pecordNo, true);
//		mongo.deleteById(MongoQueueEnum.queueFundB, pecordNo, true);
//		mongo.deleteById(MongoQueueEnum.queueFundC, pecordNo, true);
//		return true;
//	}
//	
//	/* (non-Javadoc)
//	 * @see com.niuwa.p2p.service.impl.exchange.IMatchService#syncAllQueue()
//	 */
//	@Override
//	public boolean syncAllQueue() {
//		//TODO 1.扫描mysql中掉单的借款债权项目&资金，加入到队列；
//		//TODO 2.扫描mongodb中状态为1超过1小时的task；
//		//3.version同步检查有match事件实时触发，调度里不做；
//		return true;
//	}
//
//	/**
//	 * 队列信息同步，当匹配过程中StaleObjectStateException时触发
//	 * @param loanQueue 借款或债权队列
//	 * @param loanOrClaim 借款或债权信息
//	 * @param matchingInvestList 匹配到的资金明细
//	 */
//	private void syncQueueByStaleObject(MongoQueueEnum loanQueue, DBObject loanOrClaim, LinkedList<FundResult> matchingInvestList) throws Exception {
//		ExchangeMongoDBHelper mongo = getInstance();
//		//资金的检查、同步
//		for (FundResult fv: matchingInvestList){
//			MongoQueueEnum fundQueue=fv.getQueue();
//			DBObject fund=fv.getFund();
//			String recordNo=(String) fund.get(ID);
//			try {
//				//查询MySql的最新数据
//				InvestProdRecord iprBean=investProdRecordDao.selectByPrimaryKey(recordNo);
//				if(iprBean==null || iprBean.getVersion()==null){
//					logger.warn("同步最新信息到mongodb队列异常，投资记录不存在或版本号为NULL： [recordNo："+recordNo+"]");
//					mongo.markException(fundQueue, fund,"投资记录不存在或版本号为NULL");// 标记异常
//					continue;
//				}
//				String mgVer=(String) fund.get(VERSION);
//				String mysqlVer=iprBean.getVersion().toString();
//				if(mgVer.equals(mysqlVer)){  //版本一致，解锁mongoDB中的记录
//					mongo.unLock(fundQueue, fund, true);
//				}else{ //版本不一致，更新最新的剩余投资金额、版本号到mongoDB
//					mongo.deleteById(fundQueue, recordNo, true);
//					fund.put(INVEST_SURPLUS_AMOUNT, iprBean.getRemainAmount().toPlainString());//更新最新的剩余投资金额
//					fund.put(VERSION, mysqlVer);//更新最新的版本号
//					mongo.add(fundQueue, (BasicDBObject)fund);//追加到原来的资金队列的末端
//				}
//			} catch (Exception e) {
//				logger.error("同步最新信息到mongodb队列异常，投资记录出现异常： [recordNo："+recordNo+"]",e);
//				mongo.markException(fundQueue, fund,e.getMessage());// 标记异常
//			}
//		}
//		
//		//借款or 债权的检查、同步
//		if (loanQueue != null){//为null表示资金调用，不需要同步操作
//			String loanOrClaimId=(String) loanOrClaim.get(ID);
//			String mgVer=(String) loanOrClaim.get(VERSION);
//			switch (loanQueue) {
//			case queueLoanApp:	
//			case queueLoanChannel: // app和渠道的项目
//				{
//					LoanClaim lc=loanClaimDao.selectByPrimaryKey(loanOrClaimId);
//					if(lc==null || lc.getVersion()==null){
//						logger.warn("同步最新信息到mongodb队列异常，项目记录不存在或版本号为NULL： [projectNo："+loanOrClaimId+"]");
//						mongo.markException(loanQueue, loanOrClaim,"项目记录不存在或版本号为NULL");// 标记异常
//						return;
//					}
//					String mysqlVer=lc.getVersion().toString();
//					if(mgVer.equals(mysqlVer)){  //版本一致，解锁mongoDB中的记录
//						mongo.unLock(loanQueue, loanOrClaim, true);
//						return;
//					}
//					//版本不一致，移除或更新mongoDB
//					if(ReleaseStatus.NO_MATCH.getCode().equals(lc.getReleaseStatus())){//【NO_MATCH很重要】
//						loanOrClaim.put(VERSION, mysqlVer);//更新最新的版本号
//						mongo.moveToLast(loanQueue, loanOrClaim);// 为NO_MATCH表示该笔借款版本号变化了，但还是需要匹配资金，移到队列末
//					}else{
//						mongo.deleteById(loanQueue, loanOrClaim, true);// 发布状态发生变化，不是NO_MATCH了，从借款队列中移除该借款项目
//					}
//				}
//				break;
//			case queueLoanTransfer:// 投资计划债权转让
//				{
//					String creditNo=(String) loanOrClaim.get(TR_CREDIT_NO);
//					String creditVersion=(String) loanOrClaim.get(TR_CREDIT_VERSION);
//					CustClaim custClaim =custClaimDao.selectCustClaimByCreditNo(creditNo);
//					if(custClaim==null || custClaim.getVersion()==null){
//						logger.warn("同步最新信息到mongodb队列异常，用户债权信息不存在或版本号为NULL： [creditNo："+creditNo+"]");
//						mongo.markException(loanQueue, loanOrClaim,"用户债权信息不存在或版本号为NULL");// 标记异常
//						return;
//					}
//					if(!custClaim.getVersion().toString().equals(creditVersion)){//可能还款导致version变更
//						mongo.deleteById(loanQueue, loanOrClaim, true);// 从债权转让队列中移除该借款项目
//					}
//					TransferApply ta=transferApplyDao.selectTransferApplyBySerialNo(loanOrClaimId);
//					if(ta==null || ta.getVersion()==null){
//						logger.warn("同步最新信息到mongodb队列异常，计划类债权申请信息不存在或版本号为NULL： [serialNo："+loanOrClaimId+"]");
//						mongo.markException(loanQueue, loanOrClaim,"计划类债权申请信息不存在或版本号为NULL");// 标记异常
//						return;
//					}
//					String mysqlVer=ta.getVersion().toString();
//					if(mgVer.equals(mysqlVer)){  //版本一致，解锁mongoDB中的记录
//						mongo.unLock(loanQueue, loanOrClaim, true);
//						return;
//					}
//					//版本不一致，移除或更新mongoDB
//					if(TranferStatus.NO_MATCH.getCode().equals(ta.getTranferStatus())){//【NO_MATCH很重要】
//						loanOrClaim.put(VERSION, mysqlVer);//更新最新的版本号
//						loanOrClaim.put(lOAN_AMOUNT, ta.getRemainAmount().toPlainString());//更新剩余可投金额
//						mongo.moveToLast(loanQueue, loanOrClaim);// 为NO_MATCH表示该笔债权版本号变化了，但还是需要匹配资金，移到队列末
//					}else{
//						mongo.deleteById(loanQueue, loanOrClaim, true);// 发布状态发生变化，不是NO_MATCH了，从债权转让队列中移除该借款项目
//					}
//				}
//				break;
//			default:
//				throw new Exception("未知的借款队列：" + loanQueue);
//			}
//		}
//	}
//	
//	/**
//	 * 
//	 * @param loanQueue
//	 *            借款队列，queueLoanApp、queueLoanChannel、queueLoanTransfer，    为null表示调取资金
//	 * @param loanOrClaim 借款明细
//	 * @param scanType 资金队列扫描方式(顺序)
//	 * @return 返回两个布尔值   [0]匹配情况：true-匹配成功,false-匹配失败；[1]资金队列实时情况：true-资金队列中有资金,false-资金队列中没有资金。
//	 */
//	private boolean[] match(MongoQueueEnum loanQueue, DBObject loanOrClaim, QueueScanType scanType,GatheringFoundType gatheringFoundType){
//		boolean hasFun=false;//资金队列中是否一笔都没有
//		try {
//			/*---借款相关信息---*/
//			String actualAmountStr = (String)loanOrClaim.get("_actualAmount");//（可选，自转债权调取资金的实际支付金额——投资价格）
//			String loanUserId = (String) loanOrClaim.get(USER_ID);// 借款人Id
//			BigDecimal loanAmount = actualAmountStr!=null ? new BigDecimal(actualAmountStr) : new BigDecimal((String) loanOrClaim.get(lOAN_AMOUNT));// 该笔借款额度
//			BigDecimal loanSurplusAmount = loanAmount;// 该笔当前待匹配的剩余借款
//
//			/*---投资相关信息---*/
//			LinkedList<FundResult> matchingInvestList = new LinkedList<FundResult>();// 当前借款匹配中的资金汇总
//			List<FundResult> tradeDetail = new LinkedList<FundResult>();// 交易明细
//			ExchangeMongoDBHelper mongo = getInstance();
//			FundResult fundResult = null;
//			boolean hasNewFund=true;//当前批次扫描情况，是否还有新资金
//			/*---从资金队列中匹配资金---*/
//			Long currentBatchId=System.currentTimeMillis();
//			try {
//				//执行扫描
//				while ((hasNewFund && (hasNewFund= (fundResult = findFund(scanType, currentBatchId)) != null)) //先扫描MongoDB队列中的资金
//						|| (fundResult=findFund(matchingInvestList))!=null) {//再次扫描内存记录过的资金，单笔投资记录对一笔借款多次投资信息
//					MongoQueueEnum fundQueue = fundResult.getQueue();// 资金所属队列
//					DBObject fund = fundResult.getFund();// 资金详情
//					logger.debug("  -->扫描到一笔资金： "+fundResult);
//					hasFun=true;
//					/*---单笔投资记录相关信息---*/
//					String fundUserId = (String) fund.get(USER_ID);// 投资人Id
//					if (loanUserId.equals(fundUserId)) {// 避免借款匹配到本人的投资计划
//						mongo.unLock(fundQueue, fund, true);
//						continue;
//					}
//					BigDecimal fundSurplusAmount = new BigDecimal((String) fund.get(INVEST_SURPLUS_AMOUNT));// 投资剩余金额
//					BigDecimal fundLimit = new BigDecimal((String) fund.get(LIMIT));// 单笔投资上限
//					BigDecimal singleTradeAmout = BigDecimal.ZERO;// 单笔交易额度
//					if(hasNewFund){
//						matchingInvestList.add(fundResult);     // 记录投资资金变化
//					}
//					if (fundSurplusAmount.compareTo(BigDecimal.TEN) < 0) {// 跳过，小于10元的投资剩余资金
//						fundResult.setEnable(false);//设置为无效
//						continue;
//					}
//					/*---匹配，勾兑---*/
//					BigDecimal min = loanSurplusAmount.min(fundLimit).min(fundSurplusAmount);// MIN(剩余借款、单笔投资上限、投资剩余金额)
//					loanSurplusAmount = loanSurplusAmount.subtract(min);//剩余借款额度
//					fundSurplusAmount = fundSurplusAmount.subtract(min);//剩余投资额度
//					singleTradeAmout = singleTradeAmout.add(min);//单笔交易额度
//					// 借款的零头处理，在资金足够的情况下，记账到最后一位投资者(这尽量避免了零头被匹配到新的一位投资者上)
//					if (loanSurplusAmount.compareTo(BigDecimal.TEN) < 0 && loanSurplusAmount.compareTo(fundSurplusAmount) <= 0) {
//						fundSurplusAmount = fundSurplusAmount.subtract(loanSurplusAmount);
//						singleTradeAmout = singleTradeAmout.add(loanSurplusAmount);
//						loanSurplusAmount = BigDecimal.ZERO;
//					}
//					// 更新剩余投资金额
//					fund.put(INVEST_SURPLUS_AMOUNT, fundSurplusAmount.toPlainString());
//					if (fundSurplusAmount.compareTo(BigDecimal.TEN) < 0) {// 标记，小于10元的投资剩余资金
//						fundResult.setEnable(false);//设置为无效
//					}
//					// 记录单笔交易信息
//					FundResult singleTrade= fundResult.clone();
//					singleTrade.getFund().put(SINGLE_TRADE_AMOUT, singleTradeAmout.toPlainString());// 单笔交易额度
//					tradeDetail.add(singleTrade);//记录交易明细
//					if (loanSurplusAmount.compareTo(BigDecimal.ZERO) == 0) {
//						break;
//					}
//				}
//				/*---保存处理结果---*/
//				if (loanSurplusAmount.compareTo(BigDecimal.ZERO) == 0) {// 该笔借款匹配成功
//					// 处理成功后，mysqlDB一次性处理
//					matchInnerService.batchInnerSaveMatchedResult(loanQueue, loanOrClaim, matchingInvestList, tradeDetail, gatheringFoundType);
//					// 处理成功后，mongoDB一次性处理
//					BigDecimal bg400 = BigDecimal.valueOf(400L);
//					for (FundResult fv : matchingInvestList) {
//						MongoQueueEnum mqe = fv.getQueue();
//						DBObject v = fv.getFund();
//						BigDecimal amount = new BigDecimal((String) v.get(INVEST_SURPLUS_AMOUNT));
//						long fundVersion = Long.valueOf((String) v.get(VERSION));// 投资记录版本号
//						v.put(VERSION, String.valueOf(fundVersion+1));//更新版本号，version规则与mysql保持一致
//						if (amount.compareTo(BigDecimal.TEN) < 0) {
//							mongo.deleteById(mqe, v, true);// 小于10元的投资剩余资金，从待匹配队列中移除，不再匹配
//							continue;
//						} 
//						if (mqe == MongoQueueEnum.queueFundA || mqe == MongoQueueEnum.queueFundB) {
//							if (amount.compareTo(bg400) > 0) {
//								mongo.moveToOtherLast(mqe, MongoQueueEnum.queueFundB, v);// >400的资金进入B队列
//							}else{
//								mongo.moveToOtherLast(mqe, MongoQueueEnum.queueFundC, v);// 10<=X<=400的资金进入C队列
//							}
//						} else if (mqe == MongoQueueEnum.queueFundC) {
//							mongo.moveToLast(mqe, v);// C队列的资金，处理后移到尾部
//						}else{
//							throw new Exception("未知的资金队列：" + mqe);
//						}
//					}
//					if (loanQueue != null)
//						mongo.deleteById(loanQueue, loanOrClaim, true);// 从借款队列中移除该借款项目
//					logger.info("    -->借款|债权匹配资金成功： "+loanOrClaim);
//					return new boolean[]{true,hasFun};
//				}
//			}catch (Exception e) {
//				if(ExceptionUtils.isStale(e)){
//					logger.warn("借款&投资匹配失败，数据状态已发生变化！ loanOrClaim:"+loanOrClaim, e);
//					//重新加载项目&资金信息
//					logger.debug("同步最新信息到mongodb队列开始……>>>>>> currentBatchId："+currentBatchId+", loanOrClaim:"+loanOrClaim+", matchingInvestList:"+matchingInvestList);
//					syncQueueByStaleObject(loanQueue, loanOrClaim, matchingInvestList);
//					logger.debug("同步最新信息到mongodb队列结束.  [currentBatchId："+currentBatchId+"]");
//					return new boolean[]{false,hasFun};
//				}else{
//					logger.error("借款&投资匹配出现异常！[ERR=001]，loanOrClaim: "+loanOrClaim, e);
//				}
//			}
//			/*---未匹配成功的情况---*/
//			for (FundResult fv: matchingInvestList)// 该笔借款未匹配成功，释放对应的资金
//				mongo.unLock(fv.getQueue(), fv.getFund(), true);
//			if (loanQueue != null)
//				mongo.moveToLast(loanQueue, loanOrClaim);// 该笔借款未能处理，移到队列末
//		} catch (Exception e) {
//			logger.error("借款&投资匹配服务出现异常！[ERR=002]，loanOrClaim: "+loanOrClaim, e);
//		}
//		return new boolean[]{false,hasFun};
//	}
//
//	/**
//	 * 获得一笔待匹配的投资资金（记录），从mongoDB队列中
//	 * 
//	 * @param type
//	 *            扫描方式（参见业务规则中的J1\J2）
//	 * @return 返回一个FundResult，null表示没有可用的待匹配资金
//	 */
//	private FundResult findFund(QueueScanType type,Long currentBatchId) {
//		ExchangeMongoDBHelper mongo = getInstance();
//		DBObject fund = null;
//		if (type == QueueScanType.ABC) {// 轮循3次（A-->B）-->C
//			for (int i = 1; i < 3; i++) {// 资金队列A、B扫描三次
//				if ((fund = mongo.firstAndLock(MongoQueueEnum.queueFundA, currentBatchId)) != null)
//					return new FundResult(MongoQueueEnum.queueFundA, fund);
//				if ((fund = mongo.firstAndLock(MongoQueueEnum.queueFundB, currentBatchId)) != null)
//					return new FundResult(MongoQueueEnum.queueFundB, fund);
//			}
//			if ((fund = mongo.firstAndLock(MongoQueueEnum.queueFundC, currentBatchId)) != null)
//				return new FundResult(MongoQueueEnum.queueFundC, fund);
//		} else if (type == QueueScanType.CBA) {// C-->B-->A
//			if ((fund = mongo.firstAndLock(MongoQueueEnum.queueFundC, currentBatchId)) != null)
//				return new FundResult(MongoQueueEnum.queueFundC, fund);
//			if ((fund = mongo.firstAndLock(MongoQueueEnum.queueFundB, currentBatchId)) != null)
//				return new FundResult(MongoQueueEnum.queueFundB, fund);
//			if ((fund = mongo.firstAndLock(MongoQueueEnum.queueFundA, currentBatchId)) != null)
//				return new FundResult(MongoQueueEnum.queueFundA, fund);
//		}
//		return null;
//	}
//	/**
//	 * 获得一笔待匹配的投资资金（记录），从正在记录中
//	 * @param matchingInvestList 正在匹配的资金列表
//	 * @return 返回一个FundResult，null表示没有可用的待匹配资金
//	 */
//	private FundResult findFund(LinkedList<FundResult> matchingInvestList) {
//		int len=matchingInvestList.size();
//		int step=1;//计数器
//		FundResult fund=null;
//		while (len!=0 && (fund=matchingInvestList.removeFirst())!=null) {
//			matchingInvestList.add(fund);//移至matchingFoundList末
//			if(fund.isEnable()){
//				return fund;//当前资金可用
//			}
//			if(step==len){//最后一笔也不可用
//				return null;
//			}
//			step++;
//		}
//		return fund;
//	}
//	
//	/**
//	 * 查找借款或投资计划类债权转让
//	 * 
//	 * @param targetQueue
//	 *            指定队列中查找，例如queueLoanApp、queueLoanChannel、queueLoanTransfer，
//	 *            如果为null表示所有借款队列都扫描（一般定时调度传入null）
//	 * @return 返回一个LoanResult，null表示没有可用的待匹配项目
//	 */
//	private LoanResult findLoan(MongoQueueEnum targetQueue,Long currentBatchId) {
//		DBObject loanOrClaim = null;
//		ExchangeMongoDBHelper mongo = getInstance();
//		// 从特定项目队列中获取借款项目
//		if (targetQueue != null) {
//			loanOrClaim = mongo.firstAndLock(targetQueue, currentBatchId);
//			if (loanOrClaim != null)
//				return new LoanResult(targetQueue, loanOrClaim);
//			return null;
//		}
//		// 普通的按顺序获取借款项目
//		if ((loanOrClaim = mongo.firstAndLock(MongoQueueEnum.queueLoanApp, currentBatchId)) != null)
//			return new LoanResult(MongoQueueEnum.queueLoanApp, loanOrClaim);
//		if ((loanOrClaim = mongo.firstAndLock(MongoQueueEnum.queueLoanChannel, currentBatchId)) != null)
//			return new LoanResult(MongoQueueEnum.queueLoanChannel, loanOrClaim);
//		if ((loanOrClaim = mongo.firstAndLock(MongoQueueEnum.queueLoanTransfer, currentBatchId)) != null)
//			return new LoanResult(MongoQueueEnum.queueLoanTransfer, loanOrClaim);
//		return null;
//	}
//	
//	/**
//	 * 添加借款项目到队列[同步添加至队列，异步匹配]
//	 * 
//	 * @param map ->{user_id-用户Id,_id-项目编号,loan_amount-借款金额或债权余额,version-版本号}
//	 */
//	private void doAddProject(MongoQueueEnum queue, Map<String, String> map) throws Exception{
//		try {
//			if (map.get(ID) == null || map.get(lOAN_AMOUNT) == null || map.get(VERSION) == null) {
//				throw new Exception("addLoan参数丢失！");
//			}
//			BigDecimal amout=new BigDecimal(map.get(lOAN_AMOUNT));
//			if (amout.compareTo(BigDecimal.ZERO)<=0) {
//				throw new Exception("addLoan无效参数--> [loan_amount="+amout.toPlainString()+"]");
//			}
//			ExchangeMongoDBHelper mongo = getInstance();
//			mongo.add(queue, new BasicDBObject(map));
//		} catch (Exception e) {
//			logger.error("添加借款|债权到队列失败：->" + map, e);
//			throw e;
//		}
//	}
//	
//	/**
//	 * 检查参数、最低投资额度、设置单笔投资上限金额
//	 */
//	private  boolean checkAndLimitFund(Map<String, String> map) throws Exception{
//		if (map.get(ID) == null || map.get(INVEST_AMOUNT) == null || map.get(INVEST_SURPLUS_AMOUNT) == null || map.get(VERSION) == null) {
//			throw new Exception("addFund参数丢失！");
//		}
//		// 单笔投资上限计算
//		BigDecimal investAmount = new BigDecimal(map.get(INVEST_AMOUNT));// 投资金额
//		BigDecimal investSurplusAmount = new BigDecimal(map.get(INVEST_SURPLUS_AMOUNT));// 剩余投资金额
//		if (investSurplusAmount.compareTo(BigDecimal.TEN) < 0) {// 剩余投资金额小于10元不进入队列
//			return false;
//		}
//		String limit = null;// 单笔投资上限
//		if (investAmount.compareTo(BigDecimal.valueOf(10000L)) <= 0) {// 投资金额T≤1万
//			limit = "10000";
//		} else if (investAmount.compareTo(BigDecimal.valueOf(100000L)) <= 0) {// 投资金额  1万<T≤10万
//			limit = investAmount.divide(BigDecimal.valueOf(2L)).setScale(0, RoundingMode.DOWN).toPlainString();
//		} else if (investAmount.compareTo(BigDecimal.valueOf(500000L)) <= 0) {// 投资金额 10万<T≤50万
//			limit = investAmount.divide(BigDecimal.valueOf(4L)).setScale(0, RoundingMode.DOWN).toPlainString();
//		} else if (investAmount.compareTo(BigDecimal.valueOf(2000000L)) <= 0) {// 投资金额 50万<T≤200万
//			limit = investAmount.divide(BigDecimal.valueOf(8L)).setScale(0, RoundingMode.DOWN).toPlainString();
//		} else {// 投资金额 200万<T
//			limit = investAmount.divide(BigDecimal.valueOf(10L)).setScale(0, RoundingMode.DOWN).toPlainString();
//		}
//		map.put(LIMIT, limit);//设置单笔投资上限
//		return true;
//	}
//	
//	/**
//	 * 尝试启动异步执行（如果已在执行，则忽略当前调用）
//	 * @param argetQueue 扫描的目标队列
//	 */
//	private synchronized void startExecutor(MongoQueueEnum argetQueue){
//		if(!asynRuning){
//			asynTargetQueue=argetQueue;
//			asynRuning=true;
//		}
//	}
//	/**
//	 * 停止异步执行
//	 */
//	private synchronized void stopExecutor(){
//		asynTargetQueue=null;
//		asynRuning=false;
//	}
//}
